using System;
using System.Collections.Generic;
using System.Linq;

namespace LocalDnsSdk.Commands
{
    /// <summary>
    /// 指令注册器：
    /// - 兼容旧 API（Commands 表与 GetTableRows），避免破坏现有使用点。
    /// - 新增基于 Key->指令类 的注册与解析，支持按输入解析并验证返回具体指令类实例。
    /// </summary>
    public static class CommandRegistry
    {
        // 使用 BaseCommand 集合作为命令目录
        private static readonly List<BaseCommand> _catalog = new();
        public static IReadOnlyList<BaseCommand> Commands => _catalog;

        public static List<string[]> GetTableRows()
        {
            var rows = new List<string[]> { new[] { "Command", "Format/Args", "Description" } };
            foreach (var cmd in Commands)
            {
                var desc = cmd.Description;
                var aliases = cmd.Aliases?.ToArray();
                if (aliases != null && aliases.Length > 0)
                {
                    desc = $"{desc}（别名: {string.Join(", ", aliases)}）";
                }
                rows.Add(new[] { cmd.Name, cmd.Format, desc });
            }
            return rows;
        }

        // 新增：Key->指令类 工厂映射，支持名称与别名
        private static readonly Dictionary<string, Func<BaseCommand>> _map = new(StringComparer.OrdinalIgnoreCase);

        static CommandRegistry()
        {
            // 注册所有内置指令及别名（按需扩展）
            Register(() => new StatusCommand());
            Register(() => new StartCommand());
            Register(() => new StopCommand());
            Register(() => new RestartCommand());
            Register(() => new AddCommand());
            Register(() => new AddPtrCommand());
            Register(() => new RemoveCommand());
            Register(() => new ListRecordsCommand());
            Register(() => new RemovePtrCommand());
            Register(() => new ClearRecordsCommand());
            Register(() => new ClearCacheCommand());
            Register(() => new GetCacheStatsCommand());
            Register(() => new GetConfigCommand());
            Register(() => new SetConfigCommand());
            Register(() => new SaveConfigCommand());
            Register(() => new GetStatisticsCommand());
            Register(() => new ResolveCommand());
            Register(() => new ListUpstreamCommand());
            Register(() => new SetUpstreamMainDomainCommand());
            Register(() => new ListCommandsCommand());
            Register(() => new HelpCommand());
            Register(() => new ExitCommand());
            Register(() => new SetLogPolicyCommand());
            Register(() => new GetLogStatusCommand());
        }

        /// <summary>
        /// 注册指令以及其别名（若有）。
        /// </summary>
        public static void Register(Func<BaseCommand> factory)
        {
            var instance = factory();
            _map[instance.Name] = factory;
            foreach (var alias in instance.Aliases)
            {
                _map[alias] = factory;
            }
            if (!_catalog.Any(c => string.Equals(c.Name, instance.Name, StringComparison.OrdinalIgnoreCase)))
            {
                _catalog.Add(instance);
            }
        }

        /// <summary>
        /// 解析输入并返回对应的指令类实例，同时校验参数格式。
        /// </summary>
        public static bool TryResolve(string? input, out BaseCommand? command, out string[] args, out string error)
        {
            command = null; args = System.Array.Empty<string>(); error = string.Empty;
            var parse = CommandParser.Parse(input);
            if (string.IsNullOrWhiteSpace(parse.Name)) { error = "输入为空"; return false; }
            args = parse.Args;
            // 名称规范化已在解析器完成（大写 + '-' 转 '_'）
            if (!_map.TryGetValue(parse.Name, out var factory))
            {
                error = $"未知命令: {parse.Name}";
                // 简单建议：按前缀匹配给出最多3个候选
                var suggestions = _catalog.Select(c => c.Name)
                                          .Where(n => n.StartsWith(parse.Name, StringComparison.OrdinalIgnoreCase))
                                          .Take(3)
                                          .ToArray();
                if (suggestions.Length > 0)
                {
                    error += $"。你是否指: {string.Join(", ", suggestions)}";
                }
                return false;
            }
            var instance = factory();
            if (!instance.Validate(args, out var validationError))
            {
                var aliases = instance.Aliases?.ToArray();
                var aliasText = (aliases != null && aliases.Length > 0) ? $"，别名: {string.Join(", ", aliases)}" : string.Empty;
                error = $"{validationError}（格式: {instance.Format}{aliasText}）";
                return false;
            }
            command = instance;
            return true;
        }
    }
}